`timescale 1ns / 1ps
`include "defines.vh"
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/06/14 12:41:19
// Design Name: 
// Module Name: RAM
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module RAM (
    input [0:0] rst,
    input [0:0] clk,

    input [0:0] RAM_Access_Flag_Input,

    input [`RAM_Operation_BUS] RAM_Operation_Input,
    input [`RAM_Data_BUS] RAM_Write_Data_Input,
    input [`RAM_Addr_BUS] RAM_Addr_Input,

    output [`RAM_Data_BUS] RAM_Read_Data_Output

);

    reg [0:0] Write_Flag = 0;  //RAM写标志位
    reg [`RAM_Data_BUS] Write_Data = 32'b0;  //RAM写数据

    reg [0:0] Read_Flag = 0;  //RAM读标志位

    reg [0:0] RAM_Read_Byte_Flag = 0; 
    reg [0:0] RAM_Read_Half_Word_Flag = 0;
    reg [0:0] RAM_Read_Word_Flag = 0;
    reg [0:0] RAM_Read_Byte_Unsigned_Flag = 0;
    reg [0:0] RAM_Read_Half_Word_Unsigned_Flag = 0;

    wire [`RAM_Data_BUS] RAM_Read_Data_Read_Byte;
    wire [`RAM_Data_BUS] RAM_Read_Data_Read_Half_Word;
    wire [`RAM_Data_BUS] RAM_Read_Data_Read_Word;
    wire [`RAM_Data_BUS] RAM_Read_Data_Read_Byte_Unsigned;
    wire [`RAM_Data_BUS] RAM_Read_Data_Read_Half_Word_Unsigned;





    wire [`RAM_Data_BUS] RAM_Read_Data;

    always @(*) begin
        Write_Flag = 0;
        Read_Flag = 0;
        
        RAM_Read_Byte_Flag = 0;
        RAM_Read_Half_Word_Flag = 0;
        RAM_Read_Word_Flag = 0;
        RAM_Read_Byte_Unsigned_Flag = 0;
        RAM_Read_Half_Word_Unsigned_Flag = 0;

        if (RAM_Access_Flag_Input) begin

            case (RAM_Operation_Input)
                `RAM_Write_Byte: begin
                    Write_Flag = `RAM_Write_Enabled;
                    Read_Flag  = `RAM_Read_Disabled;

                    Write_Data = {{24{1'b0}}, RAM_Write_Data_Input[7:0]};
                end



                `RAM_Write_Half_Word: begin
                    Write_Flag = `RAM_Write_Enabled;
                    Read_Flag  = `RAM_Read_Disabled;

                    Write_Data = {{16{1'b0}}, RAM_Write_Data_Input[15:0]};
                end

                `RAM_Write_Word: begin
                    Write_Flag = `RAM_Write_Enabled;
                    Read_Flag  = `RAM_Read_Disabled;

                    Write_Data = RAM_Write_Data_Input;
                end

                `RAM_Read_Byte: begin
                    Write_Flag = `RAM_Write_Disabled;
                    Read_Flag  = `RAM_Read_Enabled;

                    RAM_Read_Byte_Flag = 1;

                end

                `RAM_Read_Half_Word: begin
                    Write_Flag = `RAM_Write_Disabled;
                    Read_Flag  = `RAM_Read_Enabled;

                    RAM_Read_Half_Word_Flag = 1;
                end


                `RAM_Read_Word: begin
                    Write_Flag = `RAM_Write_Disabled;
                    Read_Flag  = `RAM_Read_Enabled;

                    RAM_Read_Word_Flag = 1;
                end

                `RAM_Read_Byte_Unsigned: begin
                    Write_Flag = `RAM_Write_Disabled;
                    Read_Flag  = `RAM_Read_Enabled;

                    RAM_Read_Byte_Unsigned_Flag =1;
                end

                `RAM_Read_Half_Word_Unsigned: begin
                    Write_Flag = `RAM_Write_Disabled;
                    Read_Flag  = `RAM_Read_Enabled;

                    RAM_Read_Half_Word_Unsigned_Flag = 1;
                end
            endcase

        end
    end


    assign RAM_Read_Data_Read_Byte = {{24{RAM_Read_Data[7]}},RAM_Read_Data[7:0]};
    assign RAM_Read_Data_Read_Half_Word = {{16{RAM_Read_Data[15]}},RAM_Read_Data[15:0]};
    assign RAM_Read_Data_Read_Word = RAM_Read_Data;
    assign RAM_Read_Data_Read_Byte_Unsigned = {{24{1'b0}},RAM_Read_Data[7:0]};
    assign RAM_Read_Data_Read_Half_Word_Unsigned =  {{16{1'b0}},RAM_Read_Data[15:0]};




    assign RAM_Read_Data_Output =(RAM_Access_Flag_Input == `RAM_Access_Flag_Enabled) ? ({32{RAM_Read_Byte_Flag}} & RAM_Read_Data_Read_Byte) | ({32{RAM_Read_Half_Word_Flag}} & RAM_Read_Data_Read_Half_Word) | ({32{RAM_Read_Word_Flag}} & RAM_Read_Data_Read_Word) | ({32{RAM_Read_Byte_Unsigned_Flag}} & RAM_Read_Data_Read_Byte_Unsigned) | ({32{RAM_Read_Half_Word_Unsigned_Flag}} & RAM_Read_Data_Read_Half_Word_Unsigned) : `Zero32;


    always @(posedge clk) begin
        if(RAM_Access_Flag_Input == 1'b1)
           $display($time,"           RAM:  Write:%d,  Read:%d",$signed(RAM_Write_Data_Input),$signed(RAM_Read_Data_Output));
    end


    TO_RAM I_RAM (
        .a  (RAM_Addr_Input >> 2),
        .d  (Write_Data),
        .clk(clk),
        .we (Write_Flag),
        .spo(RAM_Read_Data)
    );





endmodule
